package com.justech.mes.v2.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.justech.mes.dto.EquipmentType;
import com.justech.mes.utils.DateUtil;
import com.justech.mes.utils.excel.ExcelUtilsForSheet;
import com.justech.mes.v2.dao.repository.MesEquipBasicRepository;
import com.justech.mes.v2.dao.repository.MesEquipDetailRepository;
import com.justech.mes.v2.model.MesEquipBasic;
import com.justech.mes.v2.model.MesEquipDetail;
import com.justech.mes.v2.model.vo.EquipmentVo;
import com.justech.mes.v2.service.MesEquipCollectService;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;

/**
 * @author feifei.li
 */
@Service
public class MesEquipCollectServiceImpl implements MesEquipCollectService {

    @Autowired
    MesEquipBasicRepository basicRepository;

    @Autowired
    MesEquipDetailRepository detailRepository;

    /**
     * 添加数据
     *
     * @param equipmentVo
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public Object add(EquipmentVo equipmentVo) {
        final Integer ok = 1;
        final Integer no = 0;
        List<MesEquipBasic> deleteList = basicRepository.findAllByEquipmentNameAndIsOkNotAndSnAndDataTypeNot(equipmentVo.getEquipmentName(), ok, equipmentVo.getSn(), equipmentVo.getDataType());
        //删除未传完的设备
        if (!deleteList.isEmpty()) {
            deleteList.forEach(item -> {
                basicRepository.delete(item);
                detailRepository.deleteByBasicId(item.getId());
            });
        }
        Integer integer = basicRepository.countByIndexAndIsOkAndEquipmentNameAndSnAndDataType(equipmentVo.getIndex(), no, equipmentVo.getEquipmentName(), equipmentVo.getSn(), equipmentVo.getDataType());
        if (integer <= 0) {
            //类型还有设备号，
            MesEquipBasic basic = new MesEquipBasic();
            BeanUtil.copyProperties(equipmentVo, basic);
            if (basic.getIndex() == basic.getLength()) {
                basic.setIsOk(1);
                basicRepository.updateIsOk(basic.getEquipmentName(), basic.getSn(), basic.getDataType());
            } else {
                basic.setIsOk(0);
            }
            Long basicId = generateId();
            basic.setId(basicId);
            basic.setCreateTime(DateUtil.now());
            basicRepository.save(basic);
            List<String> list = equipmentVo.getData();
            for (int i = 0; i < list.size(); i++) {
                MesEquipDetail detail = new MesEquipDetail();
                detail.setBasicId(basicId);
                detail.setData(list.get(i));
                detail.setUpdateBy(String.valueOf(i));
                detail.setCreateTime(DateUtil.now());
                detailRepository.save(detail);
            }
        }
        return 1;
    }

    @Override
    public void exportExcel(String equipmentName, String sn) throws Exception {
        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
        ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletResponse response = servletRequestAttributes.getResponse();
        //新建数据标题
        String[] io = {"设备名称", "机台SN", "数据类型", "当前计数", "数据总量", "开始时间", "结束时间", "结果"};
        //导出POi
        ExcelUtilsForSheet eeu = new ExcelUtilsForSheet();
        HSSFWorkbook sheets = new HSSFWorkbook();
        //固定表头
        getFixedWatchHead(0, io, sheets, EquipmentType.IO, equipmentName, sn, eeu, byteArrayOutputStream);
        //不固定表头
        getUnstableHeaders(1, sheets, EquipmentType.AXIS_ACCURACY, equipmentName, sn, eeu, byteArrayOutputStream);
        getUnstableHeaders(2, sheets, EquipmentType.STATIC_DATA, equipmentName, sn, eeu, byteArrayOutputStream);
        getUnstableHeaders(3, sheets, EquipmentType.DYNAMIC_DATA, equipmentName, sn, eeu, byteArrayOutputStream);
        exportData(byteArrayOutputStream, response, sheets, equipmentName, sn);
    }

    /**
     * 通过流写出
     *
     * @param byteArrayOutputStream
     * @param response
     * @param sheets
     * @throws IOException
     */
    private void exportData(ByteArrayOutputStream byteArrayOutputStream, HttpServletResponse response, HSSFWorkbook sheets, String equipmentName, String sn) throws IOException {
        sheets.write(byteArrayOutputStream);
        String suffix = ".xls";
        response.setContentType("application/vnd.ms-excel;charset=utf-8");
        response.setHeader("Content-Disposition",
                "attachment;filename=" + new String(("设备对接信息" + "--" + equipmentName + "--" + sn + suffix).getBytes(), "iso-8859-1"));
        OutputStream outputStream = response.getOutputStream();
        outputStream.write(byteArrayOutputStream.toByteArray());
        outputStream.close();
        byteArrayOutputStream.close();
    }

    /**
     * 不固定表头的导出
     *
     * @param sheetNum
     * @param sheets
     * @param type
     * @param equipmentName
     * @param sn
     * @param eeu
     * @param byteArrayOutputStream
     * @throws Exception
     */
    private void getUnstableHeaders(Integer sheetNum, HSSFWorkbook sheets, String type, String equipmentName, String sn, ExcelUtilsForSheet eeu, ByteArrayOutputStream byteArrayOutputStream) throws
            Exception {
        List<MesEquipBasic> data = getData(type, equipmentName, sn);
        List<List<String>> resultData = new ArrayList<List<String>>();
        String[] headers = {"设备名称", "机台SN", "数据类型", "当前计数", "数据总量"};
        if (!data.isEmpty()) {
            for (int i = 1; i <= detailRepository.countByBasicId(data.get(0).getId()); i++) {
                headers = insert(headers, "Data" + i);
            }
        }
        getData(data, resultData);
        String title = "";
        switch (type) {
            case "1":
                title = "IO点检";
                break;
            case "2":
                title = "轴精度";
                break;
            case "3":
                title = "静态数据";
                break;
            case "4":
                title = "动态数据";
                break;
            case "5":
                title = "相机标定";
                break;
            case "6":
                title = "CPK";
                break;
            case "7":
                title = "GRR";
                break;
            case "8":
                title = "相关性";
                break;
            case "9":
                title = "压力标定";
                break;
            default:
        }
        eeu.exportExcel(sheets, sheetNum, title, headers, resultData, byteArrayOutputStream);
    }

    /**
     * 固定表头的
     *
     * @param sheetNum
     * @param head
     * @param sheets
     * @param type
     * @param equipmentName
     * @param sn
     * @param eeu
     * @param byteArrayOutputStream
     * @throws Exception
     */
    private void getFixedWatchHead(Integer sheetNum, String[] head, HSSFWorkbook sheets, String type, String equipmentName, String sn, ExcelUtilsForSheet eeu, ByteArrayOutputStream byteArrayOutputStream) throws
            Exception {
        List<MesEquipBasic> data = getData(type, equipmentName, sn);
        List<List<String>> ioDataForSheet = new ArrayList<List<String>>();
        getData(data, ioDataForSheet);
        eeu.exportExcel(sheets, sheetNum, "IO", head, ioDataForSheet, byteArrayOutputStream);
    }

    /**
     * 创建dataForSheet数据
     *
     * @param Data
     * @param DataForSheet
     */
    private void getData(List<MesEquipBasic> Data, List<List<String>> DataForSheet) {
        for (MesEquipBasic datum : Data) {
            List rowData = new ArrayList();
            List<MesEquipDetail> allByBasicId = detailRepository.findAllByBasicIdOrderByUpdateBy(datum.getId());
            setInfo(datum, rowData);
            for (MesEquipDetail equipDetail : allByBasicId) {
                rowData.add(equipDetail.getData());
            }
            DataForSheet.add(rowData);
        }
    }

    /**
     * 塞入基础数据
     *
     * @param datum
     * @param rowData
     */
    private void setInfo(MesEquipBasic datum, List rowData) {
        String title = "";
        rowData.add(datum.getEquipmentName());
        rowData.add(datum.getSn());
        switch (datum.getDataType()) {
            case "1":
                title = "IO点检";
                break;
            case "2":
                title = "轴精度";
                break;
            case "3":
                title = "静态数据";
                break;
            case "4":
                title = "动态数据";
                break;
            case "5":
                title = "相机标定";
                break;
            case "6":
                datum.setDataType("CPK");
                title = "轴精度";
                break;
            case "7":
                title = "GRR";
                break;
            case "8":
                title = "相关性";

                break;
            case "9":
                title = "压力标定";
                break;
            default:
        }
        rowData.add(title);
        rowData.add(String.valueOf(datum.getIndex()));
        rowData.add(String.valueOf(datum.getLength()));
    }

    /**
     * 分类提取数据
     *
     * @param dataType
     * @param equipmentName
     * @param sn
     * @return
     */
    private List<MesEquipBasic> getData(String dataType, String equipmentName, String sn) {
        return basicRepository.findAllByDataTypeAndEquipmentNameAndSnAndIsRepeatOrderByIndex(dataType, equipmentName, sn, 0);
    }

    private Long generateId() {
        int randomRound = 100000;
        return System.currentTimeMillis() + new Random().nextInt(randomRound);
    }

    /**
     * 往字符串数组追加新数据
     *
     * @param arr
     * @param str
     * @return
     */
    private static String[] insert(String[] arr, String str) {
        //获取数组长度
        int size = arr.length;
        //新建临时字符串数组，在原来基础上长度加一
        String[] tmp = new String[size + 1];
        //先遍历将原来的字符串数组数据添加到临时字符串数组
        for (int i = 0; i < size; i++) {
            tmp[i] = arr[i];
        }
        //在最后添加上需要追加的数据
        tmp[size] = str;
        //返回拼接完成的字符串数组
        return tmp;
    }
}
